﻿
#pragma once
#include "define.h"
#include <ostream>
#include <utility>

constexpr size_t CODE_DATA_LEN = 20;
//合约id起始位置（rb2010）
#define CONTID_BEGIN	0
//交易所id起始位置（SHFE）
#define EXCGID_BEGIN	8
//品种ID起始位置（rb）
#define CMDTID_BEGIN	14
//合约NO起始位置（2010）
#define CMDTNO_BEGIN	18

// 4996 是 Visual Studio 编译器中特定的警告编号，
// 它指的是函数被标记为“不安全”的警告。
// 这类警告通常出现在使用了如 strcpy、sprintf 等旧的 C 标准库函数时，
// Microsoft 建议使用更安全的版本（如 strcpy_s, sprintf_s）。
#if defined(WIN32)
#pragma  warning(disable:4996)
#endif

struct code_t
{
private:
	char _data[CODE_DATA_LEN];  // 私有成员变量，存储商品代码数据，长度为 CODE_DATA_LEN

public:
	// 构造函数：根据传入的字符串 cd 初始化 _data，处理商品代码的各部分
	code_t(const char* cd)
	{
		size_t ed = 0;  // 用于存储第一个遇到的 '.' 的位置
		std::memset(&_data, 0, sizeof(_data));  // 将 _data 初始化为 0
		size_t cmdtno_index = 0U;  // 记录商品代码编号的起始位置
		for (size_t i = 0; i < CODE_DATA_LEN && cd[i] != '\0'; i++)  // 遍历传入的字符
		{
			char c = cd[i];
			if (c == '.')  // 如果遇到 '.'，记录它的位置
			{
				ed = i;
				continue;
			}
			if (ed == 0)  // 如果还没遇到 '.'，处理前半部分（假设为交易所ID）
			{
				_data[i + EXCGID_BEGIN] = cd[i];  // 存入交易所ID相关位置
			}
			else  // 处理后半部分
			{
				auto c = cd[i];  // 取出当前字符
				_data[i - ed - 1] = c;  // 存入商品代码位置
				if (c >= '0' && c <= '9')  // 如果是数字，记录商品编号的起始位置
				{
					if(cmdtno_index == 0U)
					{
						cmdtno_index = i - ed - 1;
					}
				}
				else  // 否则将字符存入商品ID部分
				{
					_data[i - ed - 1 + CMDTID_BEGIN] = c;
				}
			}
		}
		// 将商品编号转为 uint16_t 并存入 _data
		*reinterpret_cast<uint16_t*>(_data + CMDTNO_BEGIN) = static_cast<uint16_t>(std::atoi(_data + cmdtno_index));
	}

	// 默认构造函数：将 _data 初始化为 0
	code_t()
	{
		std::memset(&_data, 0, sizeof(_data));
	}

	// 拷贝构造函数：将另一个 code_t 对象的 _data 拷贝到当前对象
	code_t(const code_t& obj)
	{
		std::memcpy(_data, obj._data, CODE_DATA_LEN);
	}

	// 构造函数：通过 id 和 excg_id 初始化 _data
	code_t(const char* id, const char* excg_id)
	{
		std::memset(&_data, 0, sizeof(_data));  // 初始化 _data
		size_t cmdtno_index = 0U;
		for (size_t i = 0; i < EXCGID_BEGIN && id[i] != '\0'; i++)  // 遍历 id 字符串
		{
			auto c = id[i];
			_data[i] = c;  // 将字符存入 _data
			if (c >= '0' && c <= '9')  // 如果是数字，记录商品编号的起始位置
			{
				if (cmdtno_index == 0)
				{
					cmdtno_index = i;
				}
			}
			else  // 否则存入商品ID部分
			{
				_data[i + CMDTID_BEGIN] = c;
			}
		}
		// 将商品编号转为 uint16_t 并存入 _data
		*reinterpret_cast<uint16_t*>(_data + CMDTNO_BEGIN) = static_cast<uint16_t>(std::atoi(_data + cmdtno_index));
		// 如果 excg_id 的长度小于某个范围，拷贝它到 _data 的交易所部分
		if (std::strlen(excg_id) < CMDTID_BEGIN - EXCGID_BEGIN)
		{
			std::strcpy(_data + EXCGID_BEGIN, excg_id);
		}
	}

	// 构造函数：通过 cmdt_id、cmdt_no 和 excg_id 初始化 _data
	code_t(const char* cmdt_id, const char* cmdt_no, const char* excg_id)
	{
		std::memset(&_data, 0, sizeof(_data));  // 初始化 _data
		if (std::strlen(cmdt_id) + std::strlen(cmdt_no) < EXCGID_BEGIN)
		{
			std::strcpy(_data, cmdt_id);  // 复制商品ID
			size_t cmdtno_index = strlen(_data);  // 找到商品编号的起始位置
			std::strcpy(_data + cmdtno_index, cmdt_no);  // 复制商品编号
			std::strcpy(_data + CMDTID_BEGIN, cmdt_id);  // 复制商品ID到偏移量位置
			*reinterpret_cast<uint16_t*>(_data + CMDTNO_BEGIN) = static_cast<uint16_t>(std::atoi(_data + cmdtno_index));  // 将商品编号转为 uint16_t
		}
		if (std::strlen(excg_id) < CMDTID_BEGIN - EXCGID_BEGIN)
		{
			std::strcpy(_data + EXCGID_BEGIN, excg_id);  // 复制交易所ID
		}
	}

	// 重载 `<` 操作符，用于比较两个 code_t 对象的 _data，按字典顺序比较
	bool operator < (const code_t& other)const
	{
		return std::memcmp(_data, other._data, CODE_DATA_LEN) < 0;
	}

	// 重载 `==` 操作符，比较两个 code_t 对象是否相等
	bool operator == (const code_t& other)const
	{
		return std::memcmp(_data, other._data, CODE_DATA_LEN) == 0;
	}

	// 重载 `!=` 操作符，比较两个 code_t 对象是否不相等
	bool operator != (const code_t& other)const
	{
		return std::memcmp(_data, other._data, CODE_DATA_LEN) != 0;
	}

	// 获取商品ID
	const char* get_id()const
	{
		return _data;
	}

	// 获取交易所ID，从 EXCGID_BEGIN 开始
	const char* get_excg()const
	{
		return _data + EXCGID_BEGIN;
	}

	// 获取商品ID，从 CMDTID_BEGIN 开始
	const char* get_cmdtid()const
	{
		return (_data + CMDTID_BEGIN);
	}

	// 获取商品编号，从 CMDTNO_BEGIN 开始
	uint16_t get_cmdtno()const
	{
		return *reinterpret_cast<const uint16_t*>(_data + CMDTNO_BEGIN);
	}

	// 重载 `<<` 操作符，用于将 code_t 对象输出到流中
	std::ostream& operator<<(std::ostream& os)
	{
		return os << get_id();
	}

	// 判断是否为特定的交易所
	bool is_distinct()const
	{
		if (strcmp(EXCHANGE_ID_SHFE, get_excg()) == 0)  // 判断是否为上期所
		{
			return true;
		}
		if (strcmp(EXCHANGE_ID_INE, get_excg()) == 0)  // 判断是否为上期能源
		{
			return true;
		}
		if (strcmp(EXCHANGE_ID_SGE, get_excg()) == 0)  // 判断是否为黄金交易所
		{
			return true;
		}
		if (strcmp(EXCHANGE_ID_CFFEX, get_excg()) == 0)  // 判断是否为中金所
		{
			return true;
		}
		return false;  // 否则返回 false
	}
};

// 定义默认的 code_t 对象
const code_t default_code;

struct tick_info
{
	code_t id; // 合约ID，用于标识合约的唯一代码，类型为前面定义的 code_t

	daytm_t time; // 日内时间，精确到毫秒，用于标识该行情信息的时间戳

	double_t price;  // 最新成交价，对应市场数据中的 LastPrice

	double_t open;   // 开盘价

	double_t close;  // 收盘价

	double_t high;   // 最高价

	double_t low;    // 最低价

	double_t standard; // 标准价格（根据业务逻辑可能是加权价或其他）

	uint64_t volume;  // 成交量

	uint32_t trading_day;  // 交易日期，用于标识当天交易的日期

	double_t open_interest; // 持仓量，即市场上的未平仓合约的总量

	std::array<std::pair<double_t, uint32_t>, 5> buy_order; // 买单深度：5档买单的价格和订单量，使用 `std::array` 存储五档买单
	std::array<std::pair<double_t, uint32_t>, 5> sell_order; // 卖单深度：5档卖单的价格和订单量

	// 获取买一价格，即买单中的最高出价
	double_t buy_price()const
	{
		if (buy_order.empty()) // 如果买单为空
		{
			return 0;  // 返回 0 表示无有效买价
		}
		return buy_order[0].first;  // 返回买单的第一档价格
	}

	// 获取卖一价格，即卖单中的最低出价
	double_t sell_price()const
	{
		if (sell_order.empty())  // 如果卖单为空
		{
			return 0;  // 返回 0 表示无有效卖价
		}
		return sell_order[0].first;  // 返回卖单的第一档价格
	}

	// 默认构造函数，将各个成员变量初始化为默认值
	tick_info()
		:time(0),  // 时间初始化为 0
		open(0),   // 开盘价初始化为 0
		close(0),  // 收盘价初始化为 0
		high(0),   // 最高价初始化为 0
		low(0),    // 最低价初始化为 0
		price(0),  // 最新价初始化为 0
		standard(0),  // 标准价初始化为 0
		volume(0LLU),  // 成交量初始化为 0
		trading_day(0),  // 交易日初始化为 0
		open_interest(.0F)  // 持仓量初始化为 0
	{}

	// 带参数的构造函数，使用传入的值初始化结构体中的所有成员变量
	tick_info(const code_t& cod, daytm_t dtm, double_t op, double_t cls, double_t hi, double_t lo, double_t prs, double_t std, uint64_t vlm, uint32_t td, double_t ist, std::array<std::pair<double_t, uint32_t>, 5>&& buy_ord, std::array<std::pair<double_t, uint32_t>, 5>&& sell_ord)
		:id(cod),  // 使用传入的合约ID初始化
		time(dtm),  // 使用传入的时间初始化
		open(op),  // 使用传入的开盘价初始化
		close(cls),  // 使用传入的收盘价初始化
		high(hi),  // 使用传入的最高价初始化
		low(lo),  // 使用传入的最低价初始化
		price(prs),  // 使用传入的最新价初始化
		standard(std),  // 使用传入的标准价初始化
		volume(vlm),  // 使用传入的成交量初始化
		trading_day(td),  // 使用传入的交易日初始化
		open_interest(ist),  // 使用传入的持仓量初始化
		buy_order(buy_ord),  // 使用传入的买单深度初始化
		sell_order(sell_ord)  // 使用传入的卖单深度初始化
	{}

	// 计算买单总量（所有五档买单的总成交量）
	uint32_t total_buy_valume()const
	{
		uint32_t result = 0;
		for (auto& it : buy_order)  // 遍历每档买单
		{
			result += it.second;  // 累加每档买单的订单量
		}
		return result;  // 返回总买单量
	}

	// 计算卖单总量（所有五档卖单的总成交量）
	uint32_t total_sell_valume()const
	{
		uint32_t result = 0;
		for (auto& it : sell_order)  // 遍历每档卖单
		{
			result += it.second;  // 累加每档卖单的订单量
		}
		return result;  // 返回总卖单量
	}

	// 判断该 tick_info 是否无效，依据是其 id 是否等于默认的 code_t
	bool invalid()const
	{
		return id == default_code;  // 如果 id 等于默认的 code_t，则该对象无效
	}
};

// 定义一个全局的默认 tick_info 对象
const tick_info default_tick;


enum class error_code : uint8_t
{
	EC_Success,
	EC_Failure,
	EC_OrderFieldError = 23U, //字段错误
	EC_PositionNotEnough = 30U, //仓位不足
	EC_MarginNotEnough = 31U,		//保证金不足
	EC_StateNotReady = 32, //状态不对
};

struct position_cell
{
	// 仓位，即当前持有的数量
	uint32_t	postion;
	
	// 冻结仓位，用于表示已发出的平仓指令但未成交的仓位
	uint32_t	frozen;

	// 默认构造函数，将仓位和冻结仓位初始化为 0
	position_cell() :
		postion(0),
		frozen(0)
	{}

	// 可用仓位，即总仓位减去冻结仓位
	uint32_t usable()const
	{
		return postion - frozen;  // 返回可用仓位
	}

	// 判断仓位是否为空，即是否没有持仓
	bool empty()const
	{
		return postion == 0;  // 当仓位为 0 时，返回 true
	}

	// 清空仓位和冻结仓位
	void clear()
	{
		postion = 0;  // 仓位置零
		frozen = 0;   // 冻结仓位置零
	}
};

// position_info 结构体，用于表示某个合约的完整仓位信息
struct position_info
{
	code_t id; // 合约ID，用于标识该仓位对应的合约，类型为 `code_t`

	// 带参数的构造函数，使用合约ID初始化，并将未成交的开仓数量初始化为 0
	position_info(const code_t& code) :id(code), long_pending(0), short_pending(0){}

	// 今仓（即当天开仓的持仓）- 多头仓位
	position_cell today_long;

	// 今仓 - 空头仓位
	position_cell today_short;

	// 昨仓（即前一天或之前的持仓）- 多头仓位
	position_cell history_long;

	// 昨仓 - 空头仓位
	position_cell history_short;

	// 尚未成交的开多仓指令数量
	uint32_t	long_pending;

	// 尚未成交的开空仓指令数量
	uint32_t	short_pending;

	// 判断是否所有仓位都为空
	bool empty()const
	{
		// 检查今仓、昨仓、以及未成交的开仓指令是否全部为 0
		return today_long.empty() && today_short.empty() && history_long.empty() && history_short.empty() && long_pending == 0U && short_pending == 0U;
	}

	// 获取总仓位（今仓和昨仓的多空头总仓位）
	uint32_t get_total()const
	{
		return today_long.postion + today_short.postion + history_long.postion + history_short.postion;
	}

	// 获取实际净仓位：多头仓位减去空头仓位
	int32_t get_real()const
	{
		return today_long.postion + history_long.postion - (today_short.postion + history_short.postion);
	}

	// 获取多头总仓位（今仓和昨仓的多头总量）
	uint32_t get_long_position()const
	{
		return today_long.postion + history_long.postion;
	}

	// 获取空头总仓位（今仓和昨仓的空头总量）
	uint32_t get_short_position()const
	{
		return today_short.postion + history_short.postion;
	}

	// 获取多头冻结仓位（今仓和昨仓的多头冻结总量）
	uint32_t get_long_frozen()const
	{
		return today_long.frozen + history_long.frozen;
	}

	// 获取空头冻结仓位（今仓和昨仓的空头冻结总量）
	uint32_t get_short_frozen()const
	{
		return today_short.frozen + history_short.frozen;
	}

	// 默认构造函数，将未成交的开仓数量初始化为 0
	position_info():long_pending(0U), short_pending(0U)
	{}
};

// 定义一个全局的默认 position_info 对象
const position_info default_position;


/*
 *	订单标志
 */
enum class order_flag
{
	OF_NOR = '0',		//普通订单
	OF_FAK,			//部成部撤，不等待自动撤销
	OF_FOK,			//全成全撤，不等待自动撤销
} ;

/*
 *	开平方向
 */
enum class offset_type
{
	OT_OPEN = '0',	//开仓
	OT_CLOSE,		//平仓,上期为平昨
	OT_CLSTD		//平今
};

/*
 *	多空方向
 */
enum class direction_type
{
	DT_LONG = '0',	//做多
	DT_SHORT		//做空
};

struct order_info
{
	// 订单ID，类型为 estid_t，用于唯一标识订单
	estid_t		estid;

	// 合约代码，类型为 code_t，表示该订单对应的合约
	code_t		code;

	// 交易单元ID，使用 std::string 表示，标识订单所属的交易单元
	std::string	unit_id;

	// 总数量，表示该订单的总交易量
	uint32_t	total_volume;

	// 剩余未成交的数量
	uint32_t	last_volume;

	// 订单创建时间，类型为 daytm_t，表示订单的生成时间
	daytm_t		create_time;

	// 开平仓标志，类型为 offset_type，标识该订单是开仓还是平仓
	offset_type	offset;

	// 交易方向，类型为 direction_type，表示该订单是多头（买）还是空头（卖）
	direction_type	direction;

	// 价格，表示该订单的交易价格
	double_t	price;

	// 默认构造函数，将所有字段初始化为默认值
	order_info() :
		estid(INVALID_ESTID),  // 将订单ID初始化为无效的订单ID
		offset(offset_type::OT_OPEN),  // 默认设置为开仓
		direction(direction_type::DT_LONG),  // 默认设置为多头（买）
		total_volume(0),  // 总量初始化为 0
		last_volume(0),   // 剩余未成交量初始化为 0
		create_time(0),   // 创建时间初始化为 0
		price(.0f)        // 价格初始化为 0.0
	{}

	// 判断订单是否无效（无效订单ID）
	bool invalid()const
	{
		return estid == INVALID_ESTID;  // 如果订单ID为无效ID，则订单无效
	}

	// 判断订单是否为买单（买入操作）
	bool is_buy()const
	{
		// 如果方向是多头且为开仓操作，则是买单
		if (direction == direction_type::DT_LONG && offset == offset_type::OT_OPEN)
		{
			return true;
		}
		// 如果方向是空头且为平仓操作（平今仓或平昨仓），也视为买单
		if (direction == direction_type::DT_SHORT && (offset == offset_type::OT_CLSTD || offset == offset_type::OT_CLOSE))
		{
			return true;
		}
		return false;  // 否则不是买单
	}

	// 判断订单是否为卖单（卖出操作）
	bool is_sell()const
	{
		// 如果方向是空头且为开仓操作，则是卖单
		if (direction == direction_type::DT_SHORT && offset == offset_type::OT_OPEN)
		{
			return true;
		}
		// 如果方向是多头且为平仓操作（平今仓或平昨仓），也视为卖单
		if (direction == direction_type::DT_LONG && (offset == offset_type::OT_CLOSE || offset == offset_type::OT_CLSTD))
		{
			return true;
		}
		return false;  // 否则不是卖单
	}
};

// 定义一个全局的默认订单信息对象
const order_info default_order;


//订单统计数据
struct order_statistic
{
	//下单数量
	uint32_t place_order_amount;
	//委托数量
	uint32_t entrust_amount;
	//成交数量
	uint32_t trade_amount;
	//撤单数量
	uint32_t cancel_amount;
	//错误数量
	uint32_t error_amount;

	order_statistic():
		place_order_amount(0),
		entrust_amount(0),
		trade_amount(0),
		cancel_amount(0),
		error_amount(0)
	{}

public:


	std::ostream& operator>>(std::ostream& os)
	{
		os << place_order_amount << entrust_amount;
		os << trade_amount << cancel_amount << error_amount;
		return os;
	}
};

const order_statistic default_statistic;


enum class error_type
{
	ET_PLACE_ORDER,
	ET_CANCEL_ORDER,
	ET_OTHER_ERROR
};

struct today_market_info
{
	// 合约代码，表示当前市场信息所对应的合约
	code_t code;
	
	// 成交量分布，键为价格，值为对应的成交量
	std::map<double_t, uint32_t> volume_distribution;

	// 最新的市场报价信息
	tick_info last_tick_info;

	// 获取控制价格，该价格是根据成交量分布计算得到的
	double_t get_control_price()const
	{
		// 初始化控制价格为最后一个tick的信息中的价格
		double_t control_price = last_tick_info.price;
		uint32_t max_volume = 0;

		// 遍历成交量分布，寻找成交量最大的价格点
		for (const auto& it : volume_distribution)
		{
			if (it.second > max_volume)
			{
				max_volume = it.second;  // 更新最大成交量
				control_price = it.first;  // 更新控制价格为当前价格点
			}
		}
		return control_price;  // 返回控制价格
	}

	// 清空成交量分布
	void clear()
	{
		volume_distribution.clear();
	}
};

// 定义一个全局的默认市场信息对象，使用默认构造函数初始化
const today_market_info default_today_market;


